Imports Microsoft.Win32
Imports Magic
Imports System.IO
Imports System.Collections.ObjectModel


Public Module MagicInterface

    Public tagTypes As Dictionary(Of String, Type) = HaloTag.BuildTagTypeDictionary
    Public tagExtensions As Dictionary(Of String, String) = HaloTag.BuildExtensionDictionary
    Public tagDefinitions As Dictionary(Of String, List(Of HaloTag.TagDefinition)) = HaloTag.BuildTagDefinitionDictionary
    Public magicMap As Core.HaloMap
    Public cxpe As Core.Cxpe
    Public lblStatus As ToolStripStatusLabel
    Public Sub OpenMap(ByVal filename As String, ByVal trvtags As TreeView)
        CloseMap()
        magicMap = New Magic.Core.HaloMap(filename, appSettings.CETagFolder, appSettings.CEMapFolder & "\bitmaps.map", appSettings.CEMapFolder & "\sounds.map", appSettings.XboxTagFolder, cxpe, lblStatus)
        'DisplayTree(trvtags)
    End Sub

    Public Sub CloseMap()
        If Not IsNothing(magicMap) Then
            lblStatus.Text = "Closing..."

            'trvTags.Nodes.Clear();
            magicMap.Dispose()
            magicMap = Nothing
            cxpe = Nothing
            lblStatus.Text = "Freeing allocated memory..."

            GC.Collect()
            lblStatus.Text = "Reinitializing internal structure..."

            Load()
            lblStatus.Text = "Not doing shit."
        End If
    End Sub
    Public Sub Load()
        'Try
        'Dim magicCxpe As New Magic.Core.Cxpe(New MemoryStream(My.Resources.halo))
        If File.Exists("hashlist.md5") Then
            cxpe = New Core.Cxpe(New MemoryStream(My.Resources.halo), New FileStream("hashlist.md5", FileMode.Open))
        Else
            cxpe = New Core.Cxpe(New MemoryStream(My.Resources.halo))
        End If
        'cxpe.Save()
        'cxpe.CreateVB()
        'Catch ex As Exception
        '    MessageBox.Show("Error reading internal structure data. Map and tag functions will not be available." & vbCrLf & ex.Message, "Internal Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        'End Try
    End Sub
    Public Sub Load(ByVal statusLbl As ToolStripStatusLabel)
        'Try
        If File.Exists("hashlist.md5") Then
            cxpe = New Core.Cxpe(New MemoryStream(My.Resources.halo), New FileStream("hashlist.md5", FileMode.Open))
        Else
            cxpe = New Core.Cxpe(New MemoryStream(My.Resources.halo))
        End If
        'cxpe.CreateVB()
        lblStatus = statusLbl
        'cxpe.Save()

        'Dim mscenario As New SCENARIO_TAG
        'Dim er As New Magic.Core.EndianReader(New FileStream("\\HOMESERVER\Temporary\Backup\Backup\Luis Documents\Halo Editing\tags\levels\test\bloodgulch\bloodgulch.scenario", FileMode.Open), Core.ByteOrder.BigEndian)
        'mscenario.ReadTag(er)
        'Dim ew As New Magic.Core.EndianWriter(New FileStream("C:\Tags\Test.scenario", FileMode.Create), Core.ByteOrder.BigEndian)
        'mscenario.WriteTag(ew)
        'er.Close()
        'ew.Close()

        'Catch ex As Exception
        '    MessageBox.Show("Error reading internal structure data. Map and tag functions will not be available." & vbCrLf & ex.Message, "Internal Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        'End Try
    End Sub
    Public Sub DisplayTree(ByVal trvTags As TreeView)

        Dim Tree As TreeView = trvTags
        Dim n As TreeNode
        Tree.Nodes.Clear()
        Tree.BeginUpdate()
        If Not magicMap Is Nothing Then
            For x As Integer = 0 To magicMap.Library.Count - 1
                n = New TreeNode()
                Dim sHierarchy() As String = magicMap.Library.GetName(x).Split("\")
                Array.Resize(sHierarchy, sHierarchy.Length - 1)
                n.Text = magicMap.Library.GetName(x).Substring(magicMap.Library.GetName(x).LastIndexOf("\") + 1).TrimEnd(Chr(0)) & "." & cxpe(magicMap.Library.GetClass(x)).Extension
                n.Tag = x

                Dim passCount As Integer = 0
                AddNode(sHierarchy, passCount, Tree.Nodes, n)
            Next
        End If
        Tree.Sort()
        Tree.EndUpdate()
    End Sub
    Public Sub DisplayTreeDB(ByVal trvTags As TreeView, ByVal tagDb As ReadOnlyCollection(Of String))

        Dim Tree As TreeView = trvTags
        Dim n As TreeNode
        Tree.Nodes.Clear()
        Tree.TreeViewNodeSorter = New NodeSorter
        Tree.BeginUpdate()
        For x As Integer = 0 To tagDb.Count - 1
            n = New TreeNode()
            Dim nString = tagDb(x).Replace(appSettings.XboxTagFolder & "\", "")
            Dim sHierarchy() As String = nString.Split("\")
            Array.Resize(sHierarchy, sHierarchy.Length - 1)
            n.Text = nString.Substring(nString.LastIndexOf("\") + 1).TrimEnd(Chr(0)) '& "." & cxpe(tagDb(x)).Extension
            n.Tag = "DBTAG"
            Dim passCount As Integer = 0
            AddNode(sHierarchy, passCount, Tree.Nodes, n)
        Next

        Tree.EndUpdate()
    End Sub

    Private Sub AddNode(ByRef sHierarchy() As String, ByRef Count As Integer, ByVal Parent As TreeNodeCollection, ByRef HighLevel As TreeNode)

        Dim R As Boolean = sHierarchy.Length.Equals(Count)
        Dim Node As New TreeNode()

        If (R) Then
            Dim fNode As Integer = FindNode(Parent, HighLevel.Text)
            If fNode > -1 Then
                Parent.Item(fNode).NodeFont = New Font("arial", 8, FontStyle.Bold)
            Else
                Parent.Add(HighLevel)
            End If
        Else
            Dim nInt As Integer = FindNode(Parent, sHierarchy(Count))
            If (nInt < 0) Then
                Node.Text = sHierarchy(Count)
                Node.ImageIndex = 12
                Node.SelectedImageIndex = 12
                Parent.Add(Node)
            Else
                Node = Parent(nInt)
            End If
        End If

        Count += 1
        If Not R Then AddNode(sHierarchy, Count, Node.Nodes, HighLevel)
    End Sub

    Private Function FindNode(ByVal Parent As TreeNodeCollection, ByVal Name As String)
        For Count As Integer = 0 To Parent.Count - 1
            If (Parent(Count).Text = Name) Then Return Count
        Next
        Return -1
    End Function



    'private void btnExport_Click(object sender, System.EventArgs e)
    '{
    '	if(trvTags.SelectedNode.Tag is int)
    '	{
    '		int tag = (int)trvTags.SelectedNode.Tag;
    '		string fn = tagDirectory + '\\' + map.Library.GetName(tag).TrimEnd(new char[] {'\0'}) + '.' + map.Library[tag].Xpe.Extension;
    '		lblStatus.Text = "Extracting tag '" + map.Library.GetName(tag) + '.' + map.Library[tag].Xpe.Extension + '\'';
    '		lblStatus.Refresh();
    '		if(!Directory.Exists(Path.GetDirectoryName(fn)))
    '			Directory.CreateDirectory(Path.GetDirectoryName(fn));
    '		map.Library[tag].Write(fn, map.Library);
    '		lblStatus.Text = "Successful.";
    '	}
    '	else
    '		lblStatus.Text = "Selected object is not a tag.";
    '}
End Module
